/*******************************************************************************
* Имя файла: eightTask.cpp
* Дата: 30-04-2024
* Разработчик: Андрей Подлегаев
* Группа: 315
* Факультет: ЦДО ТУСУР
* Лицензия: BSD
* Описание: Решение задач к лабораторной работе № 6 (ЦДО ТУСУР)
* *****************************************************************************/

#include "eightTask.h"

/* Реализация функции ввода (с проверкой) количества элементов контейнера */
int checkInNumberElements()
{
  std::cout << "Введите количество элементов N (от 100 до 1000): ";

  int numberElements;
  bool successfulInput{false};
  do {
      std::cin >> numberElements;
      while (std::cin.fail()) {
          std::cin.clear();
          std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
          print("Некорректный ввод!\n", COLOR_RED);
          std::cout << "Введите количество элементов N (от 100 до 1000): ";
          std::cin >> numberElements;
        }

      if (numberElements >= 100 && numberElements <= 1000) {
          successfulInput = true;
        }
      else {
          print("Введеное число элементов не входит в интервал от 100 до 1000!\n", COLOR_RED);
          std::cout << "Введите количество элементов N (от 100 до 1000): ";
        }
    } while (!successfulInput);

  return numberElements;
}

/* Реализация функции создания динамического контернейра заполненного случайными числами*/
std::vector<int> createDinamicContainer(const int xNumberElements)
{
  long seed = std::chrono::system_clock::now().time_since_epoch().count();
  std::default_random_engine rnd(seed);
  std::uniform_int_distribution<int> number(-99, 99);

  std::vector<int> vec;
  for (size_t i{1}; i <= xNumberElements; ++i) {
      vec.push_back(number(rnd));
    }
  std::cout << "Размер контейнера: " << vec.size() << " элементов.\n";
  return vec;
}

/* Реализация функции форматированного вывода контейнера (вектор) в консоль */
void printFormatContainer(std::vector<int>& vec)
{
  int countElements{};
  for (size_t i{}; i < vec.size(); ++i) {
      if (countElements == 10) {
          std::cout << '\n';
          std::cout << vec[i] << " ";
          countElements = 1;
        }
      else {
          std::cout << vec[i] << " ";
          ++countElements;
        }
    }
  std::cout << "\n\n";
}

/* Реализация функции ввода (с проверкой) однозначного числа */
short checkInSingleDigitNumber()
{
  std::cout << "Введите однозначное число k: ";

  int singleDigitNumber;
  bool successfulInput{false};
  do {
      std::cin >> singleDigitNumber;
      while (std::cin.fail()) {
          std::cin.clear();
          std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
          print("Некорректный ввод!\n", COLOR_RED);
          std::cout << "Введите однозначное число k: ";
          std::cin >> singleDigitNumber;
        }

      if (singleDigitNumber >= 1 && singleDigitNumber <= 9) {
          successfulInput = true;
        }
      else {
          print("Введеное число не является однозначным!\n", COLOR_RED);
          std::cout << "Введите однозначное число k: ";
        }
    } while (!successfulInput);

  return singleDigitNumber;
}

/* Реализация функции расчета и вывода среднего арифметического элементов кратных заданному числу */
void getArithmeticMultiplesElements(std::vector<int>& vec, const short singleDigitNumber)
{
  float countElements{};
  float sumElements{};
  for (const auto &element : vec) {
      if (element % singleDigitNumber != 0) {
          continue;
        }
      else {
          sumElements = sumElements + element;
          ++countElements;
        }
    }
  std::cout << "Сумма кратных элементов: " << sumElements << '\n';
  std::cout << "Количество кратных элементов: " << countElements << '\n';
  print("Среднее арифметическое: ", COLOR_GREEN);
  std::cout.precision(5);
  std::cout << abs(sumElements) / countElements << '\n';
}

/* Реализация функции замены заков элементов контейнера между первым и последним максимальным элементом */
std::vector<int> replacingElementSigns(std::vector<int>& vec)
{
  int maxElement = vec[0];
  int indexFirstMaxElement;
  int indexLastMaxElement;
  bool elementIsFound{false};
  std::vector<int> resultVec;

  for (size_t i{1}; i < vec.size(); ++i) {
      if (vec[i] > maxElement) {
          maxElement = vec[i];
          indexFirstMaxElement = i;
        }
      else if (vec[i] == maxElement) {
          indexLastMaxElement = i;
          elementIsFound = true;
          break;
        }
    }
  if (elementIsFound) {
      std::cout << "Индекс первого максимального элемента: " << indexFirstMaxElement << '\n';
      std::cout << "Индекс последнего максимального элемента: " << indexLastMaxElement << '\n';
      for (size_t j{}; j < vec.size(); ++j) {
          if (j > indexFirstMaxElement && j < indexLastMaxElement) {
              resultVec.push_back(vec[j] * (-1));
            }
          else {
              resultVec.push_back(vec[j]);
            }
        }
      return resultVec;
    }
  else {
      print("К сожалению последний максимальный элемент не найден! ", COLOR_RED);
      print("Возможно Ваш контейнер мал... Запустите программу заново.\n", COLOR_RED);
    }
  return resultVec;
}

/* Реализация функции замены местами элементов вектора относительно первого отрицательного элемента */
void rotationOfVectorElements(std::vector<int>& vec)
{
  size_t countElements{};
  for (size_t i{}; i < vec.size(); ++i) {
      if (i > 0) {
          if ((vec[i] < 0) && (i % 2 == 0)) {
              countElements = i;
              break;
            }
        }
    }
  std::cout << "Индекс первого четного отрицательного элемента: " << countElements
            << ',' << " значение: " << vec[countElements] << '\n';

  for (size_t j = countElements + 1; j < vec.size(); ++j) {
      vec.insert(vec.begin(), vec[j]);
      vec.erase(vec.begin() + j + 1);
    }

  for (size_t k = (vec.size() - 2); k >= (vec.size() - countElements - 1); --k) {
      vec.insert(vec.end(), vec[k]);
      vec.erase(vec.begin() + k);
    }
}

/* Реализация функции удаления всех нулевых элементов из контейнера */
void removeNullElements(std::vector<int>& vec)
{
  size_t numberElements{};
  size_t countNullElement{};

  for (const auto &element : vec) {
      if (element == 0) {
          vec.erase(vec.begin() + numberElements);
          ++countNullElement;
        }
      ++numberElements;
    }
  std::cout << "Удалено: " << countNullElement
              << " элемента/тов, размер контейнера: "  << vec.size() << '\n';
}
